import sys
import hashlib
import os
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                            QHBoxLayout, QLabel, QComboBox, QLineEdit, 
                            QPushButton, QFileDialog, QTextEdit, QMessageBox, 
                            QProgressBar)
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QFont

class HashCalculator(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('文件哈希计算器 - 版本1')
        self.setGeometry(100, 100, 500, 400)
        self.init_ui()
        
    def init_ui(self):
        # 创建中心部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建主布局
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(10, 10, 10, 10)
        main_layout.setSpacing(10)
        
        # 标题区域
        title_label = QLabel("文件哈希计算器")
        title_label.setAlignment(Qt.AlignCenter)
        font = QFont()
        font.setBold(True)
        title_label.setFont(font)
        main_layout.addWidget(title_label)
        
        # 算法选择区域
        algorithm_layout = QHBoxLayout()
        algorithm_label = QLabel("算法:")
        self.algorithm_combo = QComboBox()
        algorithms = ['MD5', 'SHA1', 'SHA256', 'SHA512']
        self.algorithm_combo.addItems(algorithms)
        algorithm_layout.addWidget(algorithm_label)
        algorithm_layout.addWidget(self.algorithm_combo)
        main_layout.addLayout(algorithm_layout)
        
        # 文件路径选择区域
        file_layout = QHBoxLayout()
        file_label = QLabel("文件:")
        self.file_path_edit = QLineEdit()
        self.file_path_edit.setPlaceholderText("输入文件路径")
        browse_button = QPushButton("浏览...")
        browse_button.clicked.connect(self.browse_file)
        file_layout.addWidget(file_label)
        file_layout.addWidget(self.file_path_edit)
        file_layout.addWidget(browse_button)
        main_layout.addLayout(file_layout)
        
        # 计算按钮
        self.calculate_button = QPushButton("计算哈希值")
        self.calculate_button.clicked.connect(self.calculate_hash)
        main_layout.addWidget(self.calculate_button)
        
        # 进度条
        progress_layout = QHBoxLayout()
        progress_label = QLabel("进度:")
        self.progress_bar = QProgressBar()
        self.progress_bar.setVisible(False)
        progress_layout.addWidget(progress_label)
        progress_layout.addWidget(self.progress_bar)
        main_layout.addLayout(progress_layout)
        
        # 哈希值显示区域
        hash_label = QLabel("哈希值:")
        main_layout.addWidget(hash_label)
        self.hash_text_edit = QTextEdit()
        self.hash_text_edit.setReadOnly(True)
        # 设置字体为等宽字体，便于查看哈希值
        font = QFont("Consolas", 10)
        self.hash_text_edit.setFont(font)
        main_layout.addWidget(self.hash_text_edit)
        
        # 复制按钮
        self.copy_button = QPushButton("复制哈希值")
        self.copy_button.clicked.connect(self.copy_hash)
        main_layout.addWidget(self.copy_button)
        
        # 底部状态区域
        self.status_label = QLabel("准备就绪")
        main_layout.addWidget(self.status_label)
    
    # 移除复杂的样式设置，使用系统默认样式
    
    # 简化版不包含拖放功能
    
    def browse_file(self):
        # 简化的文件浏览功能
        file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "所有文件 (*)")
        if file_path:
            self.file_path_edit.setText(file_path)
            self.status_label.setText(f"已选择文件")
    
    # 简化版移除自动重新计算和字符集功能
    
    def calculate_hash(self):
        file_path = self.file_path_edit.text()
        if not file_path or not os.path.isfile(file_path):
            QMessageBox.warning(self, "警告", "请先选择有效的文件")
            return
        
        algorithm = self.algorithm_combo.currentText().lower()
        
        # 更新UI状态
        self.calculate_button.setEnabled(False)
        self.progress_bar.setVisible(True)
        self.progress_bar.setValue(0)
        self.status_label.setText(f"正在计算 {self.algorithm_combo.currentText()}...")
        
        # 清空之前的哈希结果
        self.hash_text_edit.setText("")
        
        # 创建并启动工作线程
        self.worker_thread = HashWorker(file_path, algorithm)
        self.worker_thread.hash_calculated.connect(self.on_hash_calculated)
        self.worker_thread.error.connect(self.on_error)
        self.worker_thread.progress.connect(self.update_progress)
        self.worker_thread.start()
    
    def update_progress(self, progress):
        self.progress_bar.setValue(progress)
        self.status_label.setText(f"正在计算 {self.algorithm_combo.currentText()}... ({progress}%)")
    
    def on_hash_calculated(self, hash_value):
        # 简化的结果显示
        algorithm = self.algorithm_combo.currentText()
        self.hash_text_edit.setText(f"{algorithm}:\n{hash_value}")
        self.progress_bar.setVisible(False)
        self.calculate_button.setEnabled(True)
        self.status_label.setText(f"计算完成")
    
    def on_error(self, error_message):
        # 简化的错误处理
        QMessageBox.critical(self, "错误", error_message, QMessageBox.Ok)
        self.progress_bar.setVisible(False)
        self.calculate_button.setEnabled(True)
        self.status_label.setText("计算出错")
    
    def closeEvent(self, event):
        # 确保线程被正确终止
        if hasattr(self, 'worker_thread') and self.worker_thread.isRunning():
            self.worker_thread.stop()
        event.accept()
    
    def copy_hash(self):
        hash_value = self.hash_text_edit.toPlainText()
        if hash_value:
            # 复制纯哈希值，去掉算法名称前缀
            if ": " in hash_value:
                hash_value = hash_value.split(": ")[1]
            QApplication.clipboard().setText(hash_value)
            self.status_label.setText("哈希值已复制到剪贴板")

class HashWorker(QThread):
    # 定义信号
    hash_calculated = pyqtSignal(str)
    error = pyqtSignal(str)
    progress = pyqtSignal(int)
    
    def __init__(self, file_path, algorithm):
        super().__init__()
        self.file_path = file_path
        self.algorithm = algorithm
        self.is_running = True
    
    def run(self):
        try:
            # 获取哈希对象
            hash_obj = self.get_hash_object()
            
            # 计算文件大小
            total_size = os.path.getsize(self.file_path)
            block_size = 8192  # 8KB
            processed_size = 0
            
            # 分块读取文件并计算哈希
            with open(self.file_path, 'rb') as f:
                while self.is_running:
                    data = f.read(block_size)
                    if not data:
                        break
                    
                    hash_obj.update(data)
                    processed_size += len(data)
                    
                    # 计算并发送进度
                    progress = int((processed_size / total_size) * 100)
                    self.progress.emit(progress)
            
            # 发送计算结果
            if self.is_running:
                self.hash_calculated.emit(hash_obj.hexdigest())
                
        except FileNotFoundError:
            if self.is_running:
                self.error.emit(f"文件未找到")
        except PermissionError:
            if self.is_running:
                self.error.emit(f"没有权限读取文件")
        except Exception as e:
            if self.is_running:
                self.error.emit(f"计算哈希值时出错: {str(e)}")
    
    def stop(self):
        """停止哈希计算"""
        self.is_running = False
        self.wait()
    
    def get_hash_object(self):
        # 根据算法名称返回对应的哈希对象
        algorithm_map = {
            'md5': hashlib.md5,
            'sha1': hashlib.sha1,
            'sha256': hashlib.sha256,
            'sha512': hashlib.sha512
        }
        
        if self.algorithm in algorithm_map:
            return algorithm_map[self.algorithm]()
        else:
            raise ValueError(f"不支持的哈希算法: {self.algorithm}")

if __name__ == "__main__":
    # 创建应用程序实例
    app = QApplication(sys.argv)
    
    # 创建并显示主窗口
    window = HashCalculator()
    window.show()
    
    # 运行应用程序
    sys.exit(app.exec_())